package com.pointi.emoServerM;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentLinkedQueue;

import com.pointi.emoEngine.EngineData;
import com.pointi.emoTools.DefineParam;
import com.pointi.emoTools.SysGuidelineData;

public class emoServer
{
	public static void main (String [] args) throws Exception
	{
		CheckStatus _Status = null ;
		int managerLimit = 0 ;
		int managerCount = 0 ;
		int workerLimit = 0 ;
		int workerCount = 0 ;
		int mode = 2 ;

		// ____________________________________________________________________________________________________
		// Read Configuration Data | Get ServerNo

		String str_conffile = "emoServerM.conf";
		ConfigurationData conf_data = new ConfigurationData();
		conf_data.InitializeData();
		try
		{
			conf_data = conf_data.ReadConfXML(str_conffile);
			conf_data.WriteLogConfigurationData(conf_data);
		}
		catch (Exception e)
		{
			System.out.println("[EM][SVR] Can't Read XML File!! - "+str_conffile);
			e.printStackTrace();
		}
		_Status = new CheckStatus(conf_data.s_server_no, conf_data.s_check_interval) ;

		// ____________________________________________________________________________________________________
		// Get Licensed Channels

		DefineParam define = new DefineParam();
		int n_target_size = conf_data.GetLicenseChannel(conf_data.s_server_key);
		System.out.println("[EM][SVR] Licensed Channels - "+conf_data.s_server_chtype+ " : " + n_target_size);

		if (n_target_size == 0) System.out.println("[EM][SVR] Fail Check License!");
		else
		{
			// ____________________________________________________________________________________________________
			// JDBC | Connect Database

			JDBC jdbc = new JDBC() ;
			jdbc.SetDatabaseParam(conf_data) ;
			int nRet = define.DB_CONNECT_FAIL ;
			while (true) 
			{
				nRet = jdbc.fnConnectDB();
				if (nRet == define.DB_CONNECT_SUCCESS) break;
				System.out.println("[EM][CRT] Record DB Connect - "+nRet);
				Thread.sleep(1000);
			}
			EngineData engineData = new EngineData() ;

			System.out.println("[EM][SVR] Data Loading ..") ;
			jdbc.fnPrepareDatabase() ;
			jdbc.GETweight(engineData.fnWeight(), 4) ;
			jdbc.GETxsup(engineData.fnXsup(), 4) ;
			System.out.println("[EM][SVR] Start !") ;

			// ____________________________________________________________________________________________________
			// Emotion Server LifeCycle

			SysGuidelineData sysGD = new SysGuidelineData() ;
			sysGD.fnInitializeData() ;
			jdbc.fnGetSubTimeRange(sysGD) ;
			
			ConcurrentLinkedQueue<ThreadTCPServer> _TCPServer = new ConcurrentLinkedQueue<ThreadTCPServer>() ; 
			ConcurrentLinkedQueue<ThreadStatusChecker> _StatusChecker = new ConcurrentLinkedQueue<ThreadStatusChecker>() ; 

			managerLimit = Integer.valueOf(conf_data.s_manager_limit) ;
			workerLimit = Integer.valueOf(conf_data.s_worker_limit) ;
			managerCount = 0 ;
			workerCount = 0 ;
			
			ServerSocket mServerSocket = null ;
			Socket mSocket = null ;
			
			String serverPort = jdbc.fnGetServerInfo(_Status.fnGetServerNo()) ;
			if (serverPort != null)
			{
				try
				{
					mServerSocket = new ServerSocket(Integer.valueOf(serverPort)) ;
					System.out.println("[EM][SVR] Waiting for Client on Port : " + mServerSocket.getLocalPort()) ;
				}
				catch (IOException e) { e.printStackTrace() ; }
			}
			else
			{
				System.out.println("[EM][SVR] ERROR | Can't Read Server Port : Check Server Info ..") ;
			}
			boolean loopHandlerA = true ;
			while(loopHandlerA)
			{
				// ____________________________________________________________________________________________________
				// TCP Server

				if (_TCPServer.isEmpty())
					_TCPServer = new ConcurrentLinkedQueue<ThreadTCPServer>() ;
				workerCount = _TCPServer.size() ;
				_Status.fnSetServerCount(workerCount) ;
				if (workerCount < workerLimit)
				{
					try
					{
						mSocket = mServerSocket.accept() ;
						System.out.println("[EM][SVR] New Client asked for a connection ! " + mSocket.getInetAddress()) ;
						new ThreadTCPServer(_TCPServer).start(mSocket, jdbc, engineData, sysGD, Integer.valueOf(conf_data.s_conatiner_size), mode) ;
					} 
					catch (Exception e) { e.printStackTrace() ; }
				}

				// ____________________________________________________________________________________________________
				// Check Me(Server Status)

				if (_StatusChecker.isEmpty())
					_StatusChecker = new ConcurrentLinkedQueue<ThreadStatusChecker>() ;
				managerCount = _StatusChecker.size() ;
				if (managerCount < managerLimit)
					new ThreadStatusChecker(_StatusChecker).start(jdbc, _Status) ;
			}
		}
		System.out.println("[EM][SVR] END") ;		
	}
}
